home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / Reference / Amiga_Mail_Vol2 / Archives / Plain / nd90 / system / System.txt
Encoding:
Text File  |  1991-02-05  |  14.5 KB  |  392 lines

  1. (c)  Copyright 1991 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice,
  3. and is provided "as is" without warranty of any kind, either expressed
  4. or implied.  The entire risk as to the use of this information is
  5. assumed by the user.
  6.  
  7.  
  8.  
  9. Executing External Programs with Release 2.0
  10.  
  11.  
  12. by Carolyn Scheppner
  13.  
  14. The 2.0 Amiga operating system provides more flexible methods of
  15. launching programs from an application.  The 2.0 dos.library contains
  16. a new function, System(), which is more flexible and powerful than the
  17. 1.3 Execute() function.  Improvements to the con-handler, CON:, allow
  18. programs to create ``auto con'' windows, which are console windows
  19. that will only appear if input is requested from or output is sent to
  20. that console.  The 2.0 con-handler also provides several other
  21. enhancements, including Close gadgets for CON: windows and a feature
  22. which allows a program to use an existing window as its CON: window.
  23.  
  24.  
  25. The System() Function
  26.  
  27. The System() function is intended to replace the Execute() function of
  28. release 1.3.  System() spawns a shell process to execute the command
  29. line which is passed to System() as an argument.  The shell parses the
  30. command-line normally, just like command-lines typed directly into the
  31. shell's console.  If it can, System() will pass the current path and
  32. directory to the programs it launches.
  33.  
  34. The System() function can execute external commands either
  35. synchronously or asynchronously.  When System() is used synchronously,
  36. control returns to the calling program after the external program has
  37. completed.  In this case, System() returns the external program's
  38. return code, or a -1 if the command could not be found or run.  On the
  39. other hand, when System() initiates a program asynchronously, the
  40. program is no longer a concern for the caller.  The operating system
  41. will take care of the cleanup.  This is extremely useful for an
  42. application that must start up multiple programs on user demand, such
  43. as a hot key commodity.  By default, System() starts programs
  44. synchronously.  To launch a program asynchronously, use the SYS_Asynch
  45. tag with the data field set to TRUE.
  46.  
  47. With the System() call, it is easy to provide programs with specific
  48. input and output handles.  The tags SYS_Input and SYS_Output (defined
  49. in dos/dostags.h) are used to supply the input and output file
  50. handles.  A program can pass its own input and output handles to a
  51. synchronously launched program by passing the results of Input() and
  52. Output(), respectively.  Note that with a synchronous System() call,
  53. the OS will not close these handles when the spawned process exits.
  54. In the case of an asynchronously launched program, the launching
  55. program normally must provide new IO handles since the system
  56. automatically closes these handles when the asynchronous process ends.
  57. Because AmigaDOS wants separate handles for input and output, System()
  58. will automatically create an output handle if it's passed a handle for
  59. SYS_Input and NULL for SYS_Output.  This allows a program to open a
  60. CON: window for input and use it for both input and output, as
  61. System() will test to see if input is interactive and, if so, will
  62. attempt to open ``*'' for output to that console.  If the input file
  63. handle is not interactive, System() opens ``*'' on the current console
  64. task.
  65.  
  66. Programs launched using System() are not restricted to the built-in,
  67. or Boot, shell.  In the near future, System() will be able to take
  68. advantage of specially designed shells (the design requirements of
  69. these special shells have not yet been documented).  Two tags,
  70. SYS_UserShell and SYS_CustomShell, specify which shell System() should
  71. use to execute the command-line.  By using the SYS_UserShell tag with
  72. a tag value of TRUE, an application tells System() to send a command
  73. to the user's preferred shell rather that the boot shell (Note that
  74. the default user shell is the boot shell).  If an application opens a
  75. shell for the user or executes the user's command-lines, it should
  76. tell System() to use the user shell.  If an application requires
  77. consistent shell behavior, it must not use the user shell because the
  78. user can change the user shell.  Another shell tag, SYS_CustomShell,
  79. allows an application to choose other shells besides the boot and user
  80. shells.  This tag's data field should contain the custom shell's name
  81. as it appears in the system resident list.
  82.  
  83. Although it does offer many features, System() does have some
  84. limitations.  First, because command paths currently only exist in the
  85. CLI structure, Workbench (non-CLI) processes have no paths.
  86. Consequently, when a Workbench process calls a program using System(),
  87. the shell has no path to search for that program (aside from the
  88. system default search path of C: and the current directory).  A second
  89. limitation of the System() function involves CTRL-C/D/E/F handling.
  90. When a task opens a CON: window to provide a handle for a
  91. System()-launched command, that task is the owner of the handle.  This
  92. has two effects.  A System()-launched command running in that CON:
  93. window will only be able to receive CTRL-C/D/E/F signals while it is
  94. doing input or output to the window (i.e. when it has a pending read
  95. or write).  If the task that owns the handle is still around, it
  96. receives CTRL-C/D/E/F signals whenever those keys are pressed in the
  97. CON: window.
  98.  
  99.  
  100. The 2.0 Con-handler
  101.  
  102. The 2.0 con-handler (CON:) has many new enhancements that allow
  103. programs to further customize their console windows. An application
  104. requests these new features by appending keywords to the end of the
  105. CON: specification string for Open().  These keywords may appear in
  106. any order after the title string in the CON: specification.
  107.  
  108. These new keywords are:
  109.  
  110.         AUTO            Don't open CON: window until/unless input or
  111.                           output occurs
  112.         CLOSE           Put a close gadget on the CON: window
  113.         WAIT            Hold off Close until user clicks Close or types CTRL-\
  114.         WINDOW  0xaddr  Use specified window (may be on a custom screen)  
  115.         SCREEN  name    Open on specified public screen
  116.  
  117. The additional CON: keywords BACKDROP, NODRAG, NOBORDER, NOSIZE,
  118. SIMPLE, and SMART, allow control of other attributes of a CON: window.
  119.  
  120. An AUTO/CLOSE/WAIT CON: window is perfect for 2.0-specific C startup
  121. code and for asynchronous System() startup of arbitrary commands.
  122. Because of the ``auto con'' feature (AUTO), the system will never open
  123. the CON: window of a program that doesn't do any stdio (example:
  124. Calculator).  If a command does stdio input or output, the window will
  125. not open until stdio occurs. If the window opens, the wait feature
  126. (WAIT) causes the window to stay open until the user types CTRL-\ (end
  127. of file) or clicks the Close gadget.  The CLOSE keyword tells the
  128. con-handler to put a close gadget on the CON: window.
  129.  
  130.  Example: ``CON:/0/0/640/200/My Title/AUTO/CLOSE/WAIT''
  131.  
  132. The SCREEN keyword along with a public screen name allows an
  133. application to open a CON: window on that public screen.  Alternately,
  134. an application can use the WINDOW keyword to attach a console to an
  135. already open Intuition window.  The hex address of the Intuition
  136. window must follow the WINDOW keyword.  This makes it possible for
  137. System()-launched programs to do their stdio in a window on a custom
  138. screen.
  139.  
  140. The example code, SystemTest.c, provides two simple subroutines for
  141. executing external commands, and demonstrates the following 2.0
  142. features:
  143.  
  144.         o Synchronous System() command execution using the calling
  145.             program's Input()/Output(). 
  146.         o Synchronous System() command execution in a custom screen window.
  147.         o Asynchronous System() command startup with an AUTO/CLOSE/WAIT window.
  148.         o OpenScreenTags and OpenWindowTags for a 2.0 New Look window.
  149.  
  150.  
  151.  
  152.  
  153. ;/* SystemTest.c - Execute me to compile me with Lattice 5.04
  154. ;   Demonstration of System(), AUTO CON, and custom screen CON
  155. LC -b1 -cfistq -v -y -j73 SystemTest.c
  156. Blink FROM LIB:c.o,SystemTest.o TO SystemTest LIBRARY LIB:LC.lib,LIB:Amiga.lib
  157. quit
  158. */
  159.  
  160. #include <exec/types.h>
  161. #include <exec/libraries.h>
  162. #include <dos/dos.h>
  163. #include <dos/dostags.h>
  164. #include <intuition/intuition.h>
  165. #include <graphics/displayinfo.h>
  166.  
  167. #ifdef LATTICE
  168. #include <clib/exec_protos.h>
  169. #include <clib/dos_protos.h>
  170. #include <clib/intuition_protos.h>
  171. #include <stdlib.h>
  172. #include <stdio.h>
  173. #include <string.h>
  174. int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
  175. int chkabort(void) { return(0); }  /* really */
  176. #endif
  177.  
  178. /* our function error codes */
  179. #define SYSTEMFAIL      (-1L)
  180. #define WINDOWFAIL      (-2L)
  181.  
  182. /* function prototypes */
  183. LONG beginCommand(UBYTE *command);
  184. LONG doCommand(UBYTE *command, BPTR other);
  185. VOID checkResult(UBYTE *command, LONG result);
  186.  
  187.  
  188. /* Formatted version string for the 2.0 VERSION command */ 
  189. UBYTE *vers = "\0$VER: SystemTest 36.10";
  190.  
  191. struct Library *IntuitionBase;
  192.  
  193.  
  194. struct Screen *OpenScreenTags(struct NewScreen *,ULONG tags, ...);
  195. struct Window *OpenWindowTags(struct NewWindow *,ULONG tags, ...);
  196.  
  197.  
  198. void main(int argc, char **argv)
  199.     {
  200.     extern struct Library *DOSBase;
  201.     struct Screen *scr = NULL;
  202.     struct Window *win = NULL;
  203.     ULONG penspecterm = ~0;
  204.     LONG result;
  205.     BPTR file;
  206.     UBYTE *command;
  207.     UBYTE buf[128];
  208.  
  209.     if(DOSBase->lib_Version < 36)
  210.         {
  211.         printf("This example requires dos.library V36 or higher\n");
  212.         exit(RETURN_FAIL);
  213.         }
  214.     if(!(IntuitionBase = OpenLibrary("intuition.library",36)))
  215.         {
  216.         printf("This example requires intuition.library V36 or higher\n");
  217.         exit(RETURN_FAIL);
  218.         }
  219.  
  220.     /* SYNCHRONOUS SYSTEM() WITH OUR INPUT/OUTPUT
  221.      */
  222.     printf("\n*** SystemTest: Synchronous System call 'dir libs:':\n");
  223.     command = "dir libs:";
  224.     result = doCommand(command,NULL);
  225.     checkResult(command,result);
  226.     printf("\n*** SystemTest: Synchronous System call of nonexistant command:\n");
  227.     command = "badcommand";
  228.     result = doCommand(command,NULL);
  229.     checkResult(command,result);
  230.  
  231.     printf("\n*** SystemTest: Synchronous System call 'ask \"...Answer y now\"':\n");
  232.     command = 
  233.         "ask \"Ready for CON: on a Custom Screen? Answer y now (should return 5):\"";
  234.     result = doCommand(command,NULL);
  235.     checkResult(command,result);
  236.  
  237.    /* SYNCHRONOUS SYSTEM() WITH CON: IN A CUSTOM SCREEN AND WINDOW
  238.      */
  239.     if(scr = OpenScreenTags(NULL,
  240.                 SA_Width, 640,
  241.                 SA_Height, 200,
  242.                 SA_Depth, 3,
  243.                 SA_DisplayID, HIRES_KEY,
  244.                 SA_Pens, &penspecterm,  /* Give us New Look */
  245.                 TAG_DONE))
  246.         {
  247.         if(win = OpenWindowTags(NULL,
  248.                 WA_CustomScreen, scr,
  249.                 WA_Flags, WINDOWDRAG|WINDOWCLOSE|ACTIVATE,
  250.                 WA_IDCMP, CLOSEWINDOW,
  251.                 WA_Top, 20,
  252.                 WA_Height, scr->Height - 20,
  253.                 WA_Title, "Custom Window",
  254.                 WA_ScreenTitle, "Custom Screen",
  255.                 TAG_DONE))              
  256.             {
  257.             sprintf(buf,"CON://///WINDOW0x%lx", win); /* adds window pointer */
  258.             if(file = Open(buf, MODE_OLDFILE))
  259.                 {
  260.                 command = "echo \"CLI commands on a custom screen!\"";
  261.                 result = doCommand(command,file);
  262.                 command = "dir libs:";
  263.                 result = doCommand(command,file);
  264.                 command = "echo \"( Click CLOSE gadget, or type CTRL-C )\"";
  265.                 result = doCommand(command,file);
  266.                 Wait(1 << win->UserPort->mp_SigBit | SIGBREAKF_CTRL_C);
  267.                 Close(file);    /* Closes the window too */
  268.                 }
  269.             else CloseWindow(win);
  270.             }
  271.         CloseScreen(scr);
  272.         }
  273.  
  274.     printf("\n*** SystemTest: Synchronous System call 'ask \"...Answer y now\"':\n");
  275.     command = "ask \"Ready for Asynchronous demo? Answer y now (should return 5):\"";
  276.     result = doCommand(command,NULL);
  277.     checkResult(command,result);
  278.  
  279.  
  280.     /* ASYNCHRONOUS SYSTEM() WITH ON-DEMAND AUTO/WAIT CON:
  281.      */
  282.     printf("\n*** SystemTest: Asynchronous startup of 'Sys:Utilities/Clock':\n");
  283.     command = "SYS:Utilities/Clock";
  284.     result = beginCommand(command);
  285.     checkResult(command,result);
  286.  
  287.     printf("\n*** SystemTest: Asynchronous startup of 'avail':\n");
  288.     command = "avail";
  289.     result = beginCommand(command);
  290.     checkResult(command,result);
  291.  
  292.     printf("\nSystemTest exiting. Close Clock and Autocon window when you wish.\n");
  293.  
  294.     CloseLibrary(IntuitionBase);
  295.     exit(RETURN_OK);
  296.     }
  297.  
  298.  
  299.  
  300.  
  301.  
  302. /*
  303.  * Synchronous external command (wait for return)
  304.  * Uses your Input/Output unless you supply other handle
  305.  * Result will be return code of the command, unless the System() call
  306.  * itself fails, in which case the result will be -1
  307.  */
  308. LONG doCommand(UBYTE *command, BPTR other)
  309.     {
  310.     struct TagItem stags[4];
  311.  
  312.     stags[0].ti_Tag = SYS_Input;
  313.     stags[0].ti_Data = other ? other : Input();
  314.     stags[1].ti_Tag = SYS_Output;
  315.     stags[1].ti_Data = other ? NULL: Output();
  316.     stags[3].ti_Tag = TAG_DONE;
  317.     return(System(command, stags));
  318.     }
  319.  
  320.  
  321.  
  322.  
  323. /*
  324.  * Asynchronous external command started with its own autocon Input/Output
  325.  * This routine shows use of the SYS_UserShell tag as well.
  326.  * Result will only reflect whether System() call itself succeeded.
  327.  * If System() call fails, result will be -1L
  328.  * We are using -2L as result if our Open of CON: fails
  329.  */
  330. UBYTE *autocon="CON:0/40/640/150/Auto CON Window Opens if Needed/auto/close/wait";
  331. LONG beginCommand(UBYTE *command)
  332.     {
  333.     struct TagItem stags[5];
  334.     BPTR file;
  335.  
  336.     if(file = Open(autocon, MODE_OLDFILE))
  337.         {
  338.         stags[0].ti_Tag = SYS_Input;
  339.         stags[0].ti_Data = file;
  340.         stags[1].ti_Tag = SYS_Output;
  341.         stags[1].ti_Data = NULL;
  342.         stags[2].ti_Tag = SYS_Asynch;
  343.         stags[2].ti_Data = TRUE;
  344.         stags[3].ti_Tag = SYS_UserShell;
  345.         stags[3].ti_Data = TRUE;
  346.         stags[4].ti_Tag = TAG_DONE;
  347.         return(System(command, stags));
  348.         }
  349.     else return(WINDOWFAIL);
  350.     }
  351.  
  352.  
  353.  
  354.  
  355.  
  356. /*
  357.  * Demo routine outputs result of System
  358.  */
  359. VOID checkResult(UBYTE *command, LONG result)
  360.     {
  361.     if(result == SYSTEMFAIL)
  362.         printf("*** SystemTest: could not start process for command\n"); 
  363.     else if(result == WINDOWFAIL)
  364.         printf("*** SystemTest: can't open con: for command\n"); 
  365.     else
  366.         printf("*** SystemTest: command (if synchronous) returned %ld\n",result); 
  367.     }
  368.  
  369.  
  370.  
  371.  
  372.  
  373.  
  374. /*
  375.  * Stack based stubs for opening screen, window
  376.  */
  377. struct Screen *OpenScreenTags(ns, tags)
  378. struct NewScreen *ns;
  379. ULONG tags;
  380.     {
  381.     return (OpenScreenTagList(ns, (struct TagItem *)&tags));
  382.     }
  383.  
  384. struct Window *OpenWindowTags(nw, tags)
  385. struct NewWindow *nw;
  386. ULONG tags;
  387.     {
  388.     return (OpenWindowTagList(nw, (struct TagItem *)&tags));
  389.     }
  390.  
  391.  
  392.